#include "Connection.h"
#include "ConnectionMng.h"

#include "HandleTest.h"

Connection::Connection(net::io_context &ioc)
    : _ioc(ioc), _ws_ptr(std::make_unique<stream<tcp_stream> >(make_strand(ioc))) {
    boost::uuids::random_generator generator;
    const boost::uuids::uuid uuid = generator();
    _uuid = to_string(uuid);
}

std::string Connection::GetUuid() {
    return _uuid;
}

net::ip::tcp::socket &Connection::GetSocket() const {
    return get_lowest_layer(*_ws_ptr).socket();
}

void Connection::AsyncAccept() {
    auto self = shared_from_this();
    _ws_ptr->async_accept([self](const boost::system::error_code &ec) {
        try {
            if (!ec) {
                std::clog << "建立websocket连接" << std::endl;
                ConnectionMng::GetInstance().AddConnection(self);
                self->Start();
            }
            else {
                std::cerr << "error : " << ec.message() << std::endl;
            }
        }
        catch (std::exception &e) {
            std::cerr << "websocket exception is " << e.what() << std::endl;
        }
    });
}

void Connection::Start() {
    auto self = shared_from_this();
    _ws_ptr->async_read(_recv_buffer, [self](const error_code &err, std::size_t buffer_bytes) {
        try {
            if (err) {
                std::cerr << "websocket async read error is " << err.message() << std::endl;
                ConnectionMng::GetInstance().RmvConnection(self->GetUuid());
                return;
            }

            //设置数据类型为对方发来类型
            self->_ws_ptr->text(self->_ws_ptr->got_text());
            const std::string recv_data = boost::beast::buffers_to_string(self->_recv_buffer.data());
            //消耗buffer数据长度，相当于重置了缓冲区
            self->_recv_buffer.consume(self->_recv_buffer.size());
            std::cout << "websocket receive msg is " << recv_data << std::endl;
            HandleTest::GetInstance().Test(recv_data);
            // self->AsyncSend(recv_data);
            self->Start();
        }
        catch (std::exception &exp) {
            std::cerr << "exception is " << exp.what() << std::endl;
            ConnectionMng::GetInstance().RmvConnection(self->GetUuid());
        }
    });
}

void Connection::AsyncSend(const std::string &msg) { {
        std::lock_guard lck_guard(_send_mtx);
        const size_t que_len = _send_que.size();
        _send_que.push(msg);
        if (que_len > 0) {
            return;
        }
    }
    SendCallBack(msg);
}

void Connection::SendCallBack(const std::string &msg) {
    auto self = shared_from_this();
    _ws_ptr->async_write(boost::asio::buffer(msg.c_str(), msg.length()),
                         [self](const error_code &err, std::size_t size) {
                             try {
                                 if (err) {
                                     std::cerr << "async send err is " << err.message() << std::endl;
                                     ConnectionMng::GetInstance().RmvConnection(self->_uuid);
                                     return;
                                 }

                                 std::string send_msg; {
                                     std::lock_guard lck_guard(self->_send_mtx);
                                     self->_send_que.pop();
                                     if (self->_send_que.empty()) {
                                         return;
                                     }
                                     send_msg = self->_send_que.front();
                                 }
                                 self->SendCallBack(send_msg);
                             }
                             catch (std::exception &exp) {
                                 std::cout << "async send exception is " << exp.what() << std::endl;
                                 ConnectionMng::GetInstance().RmvConnection(self->_uuid);
                             }
                         });
}
